#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define Size 10

void InitBoard(char (*Board)[Size])
{
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            Board[i][j] = '.';
        }
    }
}
void PrintBoard(char (*Board)[Size])
{
    printf("    ");
    for (int i = 0; i < Size; i++)
    {
        printf("%4d", i + 1);
    }
    printf("\n");
    for (int i = 0; i < Size; i++)
    {
        printf("%4d", i + 1);
        for (int j = 0; j < Size; j++)
        {
            printf("%4c", Board[i][j]);
        }
        printf("\n");
    }
}

bool MakeMove(char (*Board)[Size], int row, int col, char player)
{
    if (row < 0 || row >= Size || col < 0 || col >= Size)
    {
        printf("非法位置！请重新输入！\n");
        return false;
    }

    if (Board[row][col] != '.')
    {
        printf("位置非空！请重新输入！\n");
        return false;
    }

    Board[row][col] = player;
    return true;
}
bool CheckIsDrawn(char (*Board)[Size])
{
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            if (Board[i][j] == '.')
                return false;
        }
    }
    return true;
}

// 是否是合法位置
bool IsValidPlace(int row, int col)
{
    if (row < 0 || row >= Size || col < 0 || col >= Size)
    {
        return false;
    }
    return true;
}
bool CheckIsWin(char (*Borad)[Size], int row, int col, char player)
{
    // 向量数组
    int direction[4][2] =
        {
            {1, 0},
            {1, 1},
            {0, 1},
            {-1, 1}};
    // 遍历四个方向，出现5个判胜
    for (int i = 0; i < 4; i++)
    {
        int count = 1;
        // 下一颗棋子的位置
        int drow = row + direction[i][0];
        int dcol = col + direction[i][1];
        while (IsValidPlace(drow, dcol) && Borad[drow][dcol] == player)
        {
            count++;
            if (count == 5)
            {
                return true;
            }
            drow = drow + direction[i][0];
            dcol = dcol + direction[i][1];
        }
        // 反方向
        drow = row - direction[i][0];
        dcol = col - direction[i][1];
        while (IsValidPlace(drow, dcol) && Borad[drow][dcol] == player)
        {
            count++;
            if (count == 5)
            {
                return true;
            }
            drow = drow - direction[i][0];
            dcol = dcol - direction[i][1];
        }
    }
    return false;
}

bool CheckIsCount(char (*Board)[Size], int row, int col, char player, int Num)
{
    // 向量数组
    int direction[4][2] =
        {
            {1, 0},
            {1, 1},
            {0, 1},
            {-1, 1}};
    // 遍历4个方向，出现五个棋子则获胜
    for (int i = 0; i < 4; i++)
    {
        int count = 1;
        // 下一颗棋子的方向
        int drow = row + direction[i][0];
        int dcol = col + direction[i][1];
        while (IsValidPlace(drow, dcol) && Board[drow][dcol] == player)
        {
            count++;
            if (count == Num)
                return true;
            drow = drow + direction[i][0];
            dcol = dcol + direction[i][1];
        }
        // 反方向找
        drow = row - direction[i][0];
        dcol = col - direction[i][1];
        while (IsValidPlace(drow, dcol) && Board[drow][dcol] == player)
        {
            count++;
            if (count == Num)
                return true;
            drow = drow - direction[i][0];
            dcol = dcol - direction[i][1];
        }
    }
    return false;
}
bool AIMakeMove(char (*Board)[Size], int PlayerRow, int PlayerCol, char player, char AI)
{
    // 智能决策  策略
    // 优先取胜策略
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            if (Board[i][j] == '.')
            {
                Board[i][j] = AI;
                if (CheckIsWin(Board, i, j, AI) == true)
                {
                    return true;
                }
                else
                    Board[i][j] = '.';
            }
        }
    }
    // 阻止对手策略
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            if (Board[i][j] == '.')
            {
                Board[i][j] = player;
                if (CheckIsWin(Board, i, j, player) == true)
                {
                    Board[i][j] = AI;
                    return false;
                }
                Board[i][j] = '.';
            }
        }
    }

    // 阻止对手连成4个
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            if (Board[i][j] == '.')
            {
                Board[i][j] = player;
                if (CheckIsCount(Board, i, j, player, 4) == true)
                {
                    Board[i][j] = AI;
                    return false;
                }
                Board[i][j] = '.';
            }
        }
    }
    // 阻止对手连成3个
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            if (Board[i][j] == '.')
            {
                Board[i][j] = player;
                if (CheckIsCount(Board, i, j, player, 3) == true)
                {
                    Board[i][j] = AI;
                    return false;
                }
                Board[i][j] = '.';
            }
        }
    }
    // 阻止对手连成2个
    for (int i = 0; i < Size; i++)
    {
        for (int j = 0; j < Size; j++)
        {
            if (Board[i][j] == '.')
            {
                Board[i][j] = player;
                if (CheckIsCount(Board, i, j, player, 2) == true)
                {
                    Board[i][j] = AI;
                    return false;
                }
                Board[i][j] = '.';
            }
        }
    }
}
void Single()
{
    char Board[Size][Size] = {0};
    InitBoard(Board);
    // PrintBoard(Board);
    char player = 'X';
    int row, col;
    while (1)
    {
        PrintBoard(Board);

        if (player == 'X')
        {
            printf("请|%c|选手下棋：", player);
            scanf("%d %d", &row, &col);
            if (MakeMove(Board, row - 1, col - 1, player) == false)
                continue;
        }
        else
        {
            printf("AI正在下棋...\n");
            if (AIMakeMove(Board, row - 1, col - 1, 'X', 'O') == true)
            {
                printf("AI获胜!\n");
                break;
            }
        }
        if (CheckIsWin(Board, row - 1, col - 1, player) == true)
        {
            printf("恭喜|%c|选手获胜！\n", player);
            break;
        }
        if (CheckIsDrawn(Board) == true)
        {
            PrintBoard(Board);
            printf("平局！\n");
            break;
        }
        player = (player == 'X') ? 'O' : 'X';
    }
}

void Double()
{
    char Board[Size][Size] = {0};
    InitBoard(Board);
    // PrintBoard(Board);
    char player = 'X';
    while (1)
    {
        PrintBoard(Board);
        int row, col;
        {
            printf("请|%c|选手下棋：", player);
            scanf("%d %d", &row, &col);
            if (MakeMove(Board, row - 1, col - 1, player) == false)
                continue;
        }
        if (CheckIsWin(Board, row - 1, col - 1, player) == true)
        {
            printf("恭喜|%c|选手获胜！\n", player);
            break;
        }
        if (CheckIsDrawn(Board) == true)
        {
            PrintBoard(Board);
            printf("平局！\n");
            break;
        }
        player = (player == 'X') ? 'O' : 'X';
    }
}

int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        printf("缺少启动参数!\n");
        return 0;
    }

    // 如果  1 ： 单机   2 ： 双人游戏
    if (strcmp(argv[1], "1") == 0)
    {
        Single();
    }
    else
    {
        Double();
    }
    return 0;
}